package org.example.io;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;
import org.example.io.handler.*;
import org.example.io.handler.server.CreateGroupRequestPacketHandler;

@Slf4j
public class NettyServer {
    public static void main(String[] args) {
        ServerBootstrap bootstrap = new ServerBootstrap();
        // 1、定义线程模型
        NioEventLoopGroup acceptor = new NioEventLoopGroup();
        NioEventLoopGroup worker= new NioEventLoopGroup();
        bootstrap.group(acceptor, worker);

        // 2、定义IO模型为NIO模型
        bootstrap.channel(NioServerSocketChannel.class);

        // 3、常用配置
        // 开启底层TCP心跳
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
        // TCP不延迟，立马发送消息
        bootstrap.option(ChannelOption.TCP_NODELAY, false);

        bootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                ch.pipeline().addLast(new SpliterHandler());
                ch.pipeline().addLast(new PacketDecoder());
                ch.pipeline().addLast(new LoginRequestPacketHandler());
                ch.pipeline().addLast(new AuthHandler());
                ch.pipeline().addLast(new MessageRequestPacketHandler());
                ch.pipeline().addLast(new CreateGroupRequestPacketHandler());
                ch.pipeline().addLast(new PacketEncoder());

            }
        });

        try {
            ChannelFuture channelFuture = bootstrap.bind(8000).addListener(new GenericFutureListener<Future<? super Void>>() {
                @Override
                public void operationComplete(Future<? super Void> future) throws Exception {
                    if (future.isSuccess()) {
                        log.info("IM服务启动成功");
                    } else {
                        log.info("IM服务启动失败：{}", future.cause());
                    }
                }
            }).sync();

            // 等待关闭
            Channel channel = channelFuture.channel();
            channel.closeFuture().sync();
            log.info("IM服务终止");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // 优雅关闭
            acceptor.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}
